package com.projectbox.service.impl;


import java.util.ArrayList;
import java.util.List;

import java.util.Calendar;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.projectbox.dao.ProjectDao;
import com.projectbox.dao.UserDao;
import com.projectbox.model.Project;
import com.projectbox.model.User;
import com.projectbox.service.ProjectService;
import com.projectbox.utility.EmailUtility;
import com.projectbox.utility.ResourceStorageUtility;

public class ProjectServiceImpl implements ProjectService {

	private ProjectDao projectDao;
	private UserDao userDao;
	private ResourceStorageUtility resourceStorageUtility;
	private EmailUtility emailUtility;
	
	private Logger logger = LoggerFactory.getLogger(getClass());
	
	public void setEmailUtility(EmailUtility emailUtility) {
		this.emailUtility = emailUtility;
	}
	
	public void setResourceStorageUtility(ResourceStorageUtility resourceStorageUtility) {
		this.resourceStorageUtility = resourceStorageUtility;
	}
	
	public void setUserDao(UserDao userDao) {
		this.userDao = userDao;
	}
	
	public void setProjectDao(ProjectDao projectDao) {
		this.projectDao = projectDao;
	}
	
	/**
	 * Returns all projects
	 */
	public List<Project> findAllProjects() {
		return this.setProjectManager(projectDao.getAllProjects());
	}

	public List<Project> findManagedProjects(User user) {
		return this.setProjectManager(projectDao.getProjectsByManager(user.getId()));
	}

	public List<Project> findContributedProjects(User user) {
		return this.setProjectManager(this.projectDao.getContributedProjects(user.getId()));
	}

	public List<Project> findNonContributedProjects(User user) {
		List<Project> projectList
			= this.projectDao.getNoncontributedProjects(user.getId());
		
		this.setProjectManager(projectList);
		this.setProjectStatus(user.getId(), projectList);
		return projectList;
	}
	
	public List<Project> findNonContributedProjects(User user, boolean privacy) {
		List<Project> projectList
			= this.projectDao.getNoncontributedProjects(user.getId());
		List<Project> resultList = null;
		
		if (projectList != null) {
			resultList = new ArrayList<Project>();
			for (Project p : projectList) {
				if (p.getPrivacy() == privacy) {
					resultList.add(p);
				}
			}
			
			if (privacy) {
				this.setProjectStatus(user.getId(), resultList);
			}
		}
		
		this.setProjectManager(resultList);
		return resultList;
	}

	public List<User> findProjectContributor(Long pid) {
		return projectDao.getProjectContributors(pid);
	}
	
	public List<User> findProjectPendingUser(Long pid) {
		return projectDao.getProjectPendingUsers(pid);
	}

	public boolean addNewProject(String name, String description,
			boolean isPrivate, Long mid) {
		
	    Calendar cal = Calendar.getInstance();
	    
	    cal.set(Calendar.HOUR_OF_DAY, 0);            // set hour to midnight
	    cal.set(Calendar.MINUTE, 0);                 // set minute in hour
	    cal.set(Calendar.SECOND, 0);                 // set second in minute
	    cal.set(Calendar.MILLISECOND, 0); 
	    
		Project project = new Project();
		project.setName(name);
		project.setDescription(description);
		project.setPrivate(isPrivate);
		project.setMid(mid);
		project.setTimeCreated(cal.getTimeInMillis());
		project.setTimeModified(cal.getTimeInMillis());
		logger.debug("Project Creation time: " + cal.getTimeInMillis());
		
		try {
			projectDao.insert(project);
		} catch (Exception e) { // TODO: get the correct SQL Exception
			return false;
		}
		
		logger.debug("Crear Project Name: " + project.getName() + " id:" + project.getId());
		
		this.resourceStorageUtility.createProjectDirectory(project.getId());
		
		return true;
	}

	public boolean deleteProject(Long pid) {
		Project project = projectDao.getProjectById(pid);
		this.resourceStorageUtility.deleteProjectDirectory(project);
		projectDao.delete(pid);
		return true;
	}

	public boolean addProjectContributor(Long pid, Long uid) {
		
		String status = this.projectDao.getAccessStatus(uid, pid);
		logger.debug("addProjectContributor: " + uid + " " + pid + ": " + status);
		
		if (status != null) {
			if (status.equals("pending")) {
				this.projectDao.saveAccess(uid, pid, "granted");
				
				User contributor = this.userDao.getUserById(uid);
				Project project = this.projectDao.getProjectById(pid);
				
				logger.debug("send email to ");
				
				String msg = "You are now a contributor of " + project.getName() + "!!";
				this.emailUtility.sendMail("admin@projectbox.com", contributor.getUsername(),
						"You are approve!!", msg);
				
			} else if (status.equals("granted")) {
				// do nothing
			} else {
				logger.debug("something is wrong, delete the access record");
				this.projectDao.deleteAccess(uid, pid);
			}
			
		} else {
			this.projectDao.saveAccess(uid, pid, "granted");
		}
		
		return true;
	}

	public boolean removeProjectContributor(Long pid, Long uid) {
		String subject = "";
		String msg = "";
		User contributor = this.userDao.getUserById(uid);
		Project project = this.projectDao.getProjectById(pid);
		
		String status = this.projectDao.getAccessStatus(uid, pid);
		logger.debug("removeProjectContributor: " + uid + " " + pid + ": " + status);
		
		if (status != null) {
			if (status.equals("granted")) {
				logger.debug("remove previous contributor");
				
				subject = "You had been remove";
				msg = "You are no longer a project contributor for project " + project.getName();
			}
			
			if (status.equals("pending")) {
				logger.debug("reject contributor request");
				
				subject = "Your project participation request is rejected";
				msg = "You are not approve to participate project " + project.getName();
			}
			
			this.emailUtility.sendMail("admin@projectbox.com", contributor.getUsername(), subject, msg);
		}

		this.projectDao.deleteAccess(uid, pid);
		return true;
	}
	
	public void processProjectContributorRequest(Project project, User contributor) {
		if (project.getPrivacy()) {
			logger.debug("the project is private");
			this.projectDao.saveAccess(contributor.getId(), project.getId(), "pending");
			
			// get the project manager
			User projectManager = project.getManager();
			if (projectManager == null) {
				projectManager = this.userDao.getUserById(project.getId());
			}
			
			String msg = contributor.getFirstName() + " " + contributor.getLastName()
					+ " wants to participate your project " + project.getName();
			
			logger.debug("send email to project manager " + projectManager.getUsername());
			this.emailUtility.sendMail("admin@projectbox.com", projectManager.getUsername(), 
					"You have contributor request", msg);
		} else {
			logger.debug("the project is public");
			this.projectDao.saveAccess(contributor.getId(), project.getId(), "granted");
		}
	}

	public Project findProject(Long pid) {
		Project p = null;
		p = this.projectDao.getProjectById(pid);
		if (p != null) {
			p.setManager(this.userDao.getUserById(p.getMid()));
		}
		return p;
	}
	
	public Project findProject(String name) {
		Project p = null;
		p = this.projectDao.getProjectByName(name);
		if (p != null) {
			p.setManager(this.userDao.getUserById(p.getMid()));
		}
		return p;
	}
	
	private List<Project> setProjectManager(List<Project> projectList) {
		if (projectList != null) {
			for (Project p : projectList) {
				p.setManager(this.userDao.getUserById(p.getMid()));
			}
		}
		
		return projectList;
	}
	
	private List<Project> setProjectStatus(Long uid, List<Project> projects){
		
		for (Project p : projects){
			String status = projectDao.getAccessStatus(uid, p.getId());
			p.setUserStatus(status);
		}
		
		return projects;
	}
	
	public String getProjectStatus(Long uid, Project p) {
		String status = projectDao.getAccessStatus(uid, p.getId());
		if (status == null) {
			status = "";
		}
		
		return status;
	}
	
	

}
